import { FastifyReply, FastifyRequest } from 'fastify';
import axios, { AxiosRequestConfig, AxiosResponse } from 'axios';
import { ModelAppFactory } from '../app';
import { HttpStatus } from '@nestjs/common';

/**
 * @description Http网络请求对象
 * @export
 * @class Http
 */
export class Http {

  /**
   * @description Http网络请求对象实例
   * @static
   * @type {Http}
   * @memberof Http
   */
  static instance: Http;

  /**
   * @description 获取Http网络请求对象
   * @static
   * @return {*}  {Http}
   * @memberof Http
   */
  static getInstance(): Http {
    if (!this.instance) {
      this.instance = new Http();
    }
    return this.instance;
  }

  /**
   * 添加拦截器
   * @memberof Http
   */
  public constructor() {
    axios.interceptors.request.use((config: any) => {
      delete config.headers['Content-Length'];
      delete config.headers['content-length'];
      return config;
    }, (error: any) => {
      return Promise.reject(error);
    });

    axios.interceptors.response.use((response: any) => {
      return response;
    }, (error: any) => {
      return Promise.reject(error);
    });
  }

  /**
   * get请求
   *
   * @param {FastifyRequest} request
   * @param {FastifyReply} response
   * @param {string} url
   * @param {AxiosRequestConfig} [config]
   * @return {*}  {Promise<AxiosResponse<any>>}
   * @memberof Http
   */
  async get(
    request: FastifyRequest,
    response: FastifyReply,
    url: string,
    config?: AxiosRequestConfig,
  ): Promise<AxiosResponse<any>> {
    config = this.parameterProcessing(request, config);
    try {
      const app = ModelAppFactory.getInstance().getActiveApp();
      const res = await axios.get(`${app.host}${url}`, config);
      return res;
    } catch (err) {
      this.errorProcessing(response, err);
    }
  }

  /**
   * @description post请求
   * @param {FastifyRequest} request
   * @param {FastifyReply} response
   * @param {string} url
   * @param {*} [data]
   * @param {AxiosRequestConfig} [config]
   * @return {*}  {Promise<AxiosResponse<any>>}
   * @memberof Http
   */
  async post(
    request: FastifyRequest,
    response: FastifyReply,
    url: string,
    data?: any,
    config?: AxiosRequestConfig,
  ): Promise<AxiosResponse<any>> {
    config = this.parameterProcessing(request, config);
    const app = ModelAppFactory.getInstance().getActiveApp();
    try {
      const res = await axios.post(`${app.host}${url}`, data || {}, config);
      return res;
    } catch (err) {
      this.errorProcessing(response, err);
      return err.response;
    }
  }

  /**
   * @description 格式化请求配置
   * @protected
   * @param {FastifyRequest} request
   * @param {AxiosRequestConfig} config
   * @return {*} 
   * @memberof Http
   */
  protected parameterProcessing(request: FastifyRequest, config: AxiosRequestConfig) {
    if (!config) {
      config = {};
    }
    if (request) {
      config.headers = Object.assign(request.headers, config.headers || {});
    }
    return config;
  }

  /**
   * @description 统一错误拦截
   * @protected
   * @param {FastifyReply} res
   * @param {*} err
   * @memberof Http
   */
  protected errorProcessing(res: FastifyReply, err: any): void {
    if (err.response) {
      console.error('', `请求地址: ${err.config.url}`);
      console.error('', err.response.data);
      res.code(err.response.status).send(err.response.data);
    } else {
      console.error('', err.message);
      res.code(HttpStatus.INTERNAL_SERVER_ERROR).send(err.message);
    }
  }
}